#!/bin/bash
VERSION='2.0'

GNAPNAME=$(basename "$0")
echo "GNAP remastering tool ${GNAPNAME} ${VERSION}"
GNAPCORE='/usr/lib/gnap/gnap-core.tar'
GNAPBASEFS='/usr/lib/gnap/gnap-basefs.tar.bz2'
GNAPEXTDIR='/usr/lib/gnap/extensions'
OUTPUT='mygnap-core.tar'
TEMPDIR=''

G=$'\e[32;01m'
B=$'\e[31;01m'
N=$'\e[0m'
W=$'\e[33;01m'
K=$'\e[34;01m'
C="$[$(set -- $(stty size 2>/dev/null); echo ${2}) - 7]"
E=$'\e['${C}'G'

gwarn() {
	echo -e " ${W}*${N} ${*}"
}

gconfirm() {
	if [[ "${FORCEYES}" -eq 1 ]]; then
		gwarn "${*} forced to yes"
	else
		read -ep " ${W}*${N} ${*} [N]: " answer
		if [[ "${answer}" != 'y' && "${answer}" != 'Y' ]]; then
			if [[ -n "${TEMPDIR}" ]]; then
				cleanup
			fi
			echo 'Remaster aborted !'
			exit 2
		fi
	fi
}

gbegin() {
	echo -ne " ${G}*${N} ${*}..."
}

gtest() {
	continued=0
	if [[ "$#" -gt 0 && "${1}" == 'continued' ]]; then
		shift
		continued=1
	fi

	if [[ "${#}" -eq 0 || "${1}" -eq 0 ]]; then
		if [[ "${continued}" -eq 0 ]]; then
			echo -e "${E}  ${K}[ ${G}ok${K} ]${N}"
		fi
	else
		echo -e "${E}  ${K}[ ${B}!!${K} ]${N}"
		if [[ "$#" -ge 2 ]]; then
			shift
			echo -en " ${B}*${N} ${*}"
			echo -e "${E}  ${K}[ ${B}!!${K} ]${N}"
		fi
		if [[ -n "${TEMPDIR}" ]]; then
			cleanup
		fi
		echo "Remaster failed, try ${GNAPNAME} -h for more help"
		exit 1
	fi
}

usage() {
	echo
	echo 'Usage:'
	echo "  ${GNAPNAME} [ options ]"
	echo
	echo 'Options:'
	echo '  -e extension    Extension to include in core file'
	echo '  -k kerneltbz2   Kernel to use in core file'
	echo '  -m moduletbz2   Modules to use in core file'
	echo '  -o output       Output core name'
	echo '  -g gnap_core    Original GNAP core file'
	echo '  -b basefs       basefs.tar.bz2 file to use as base'
	echo '  -d extdir       Directory where to find extensions'
	echo '  -f              Force all answers to yes (dangerous !)'
	echo
	echo "Please man ${GNAPNAME} for more details."
}

cleanup() {
	gbegin 'Cleaning temporary directories'
	if [[ -d "${TEMPDIR}" ]]; then
		DIRTOREMOVE="${TEMPDIR}"
		TEMPDIR=''
	 	rm -rf "${DIRTOREMOVE}"
		gtest $? "Failed to remove ${DIRTOREMOVE}"
	else
		gtest 0
	fi
}

if [[ "$#" -eq 0 || "${1}" == '-h' ]]; then
	usage
	exit 0
fi

gbegin 'Checking parameters'

# Read options
while getopts ':he:k:m:o:g:b:d:f' options; do
	case ${options} in
		h ) usage
			exit 0;;
		e ) EXTENSIONS="${EXTENSIONS} ${OPTARG}";;
		k ) KERNEXT="${OPTARG}";;
		m ) MODEXT="${OPTARG}";;
		o ) OUTPUT="${OPTARG}";;
		g ) GNAPCORE="${OPTARG}";;
		b ) GNAPBASEFS="${OPTARG}";;
		d ) GNAPEXTDIR="${OPTARG}";;
		f ) FORCEYES=1;;
		* ) gtest 1 'Specified options are incomplete or unknown !';;
	esac
done

# Root is needed
test "${EUID}" -eq 0
gtest continued $? "You need to be root to run ${GNAPNAME}"

# basefs file is required
test -f "${GNAPBASEFS}"
gtest continued $? 'Please specify a valid GNAP basefs file (-b option)'

# core file is required
test -f "${GNAPCORE}"
gtest continued $? 'Please specify a valid GNAP core file (-g option)'

# At least one operation is required
test -n "${EXTENSIONS}" -o -n "${KERNEXT}" -o -n "${MODEXT}"
gtest $? 'Please specify at least one operation (-e, -k, -m) to perform'

# Confirm tarball overwrite
if [[ -e "${OUTPUT}" ]]; then
	gconfirm "${OUTPUT} already exists, overwrite"
fi

# Preparing new FS
gbegin "Unpacking ${GNAPBASEFS} basefs"
TEMPDIR=$(mktemp -d -t gnap_remaster.XXXXXX)
gtest continued $? 'Failed to create temporary directory'
TEMPOVERDIR="${TEMPDIR}/basefs"
mkdir "${TEMPOVERDIR}"
gtest continued $? 'Failed to create basefs temporary subdirectory'

tar jx -C "${TEMPOVERDIR}" -f "${GNAPBASEFS}"
gtest $? 'Failed to unpack basefs'

for overlay in ${EXTENSIONS} ; do
	gbegin "Adding ${overlay} extension"
	test -f "${GNAPEXTDIR}/gnapext_${overlay}.tbz2"
	gtest continued $? "${GNAPEXTDIR}/gnapext_${overlay}.tbz2 does not exist"
	tar jxf "${GNAPEXTDIR}/gnapext_${overlay}.tbz2" -C "${TEMPOVERDIR}"
	gtest $? "${overlay} is not a valid extension (tbz2 format)"
done

# Preparing new core
gbegin 'Extracting core tarball'
TEMPCOREDIR="${TEMPDIR}/core"
mkdir "${TEMPCOREDIR}"
gtest continued $? 'Failed to create core temporary subdirectory'

tar x -C "${TEMPCOREDIR}" -f "${GNAPCORE}" --exclude image.squashfs
gtest $? 'Failed to extract core'

if [[ -f "${KERNEXT}" ]]; then
	gbegin "Replacing kernel and initrd using ${KERNEXT}"
	TEMPKERNDIR="${TEMPDIR}/kernel"
	mkdir "${TEMPKERNDIR}"
	gtest continued $? 'Failed to create kernel temporary subdirectory'

	tar jx -C "${TEMPKERNDIR}" -f "${KERNEXT}"
	gtest continued $? 'Failed to extract kernpackage'
	cp ${TEMPKERNDIR}/kernel* "${TEMPCOREDIR}/isolinux/gentoo" && \
		cp ${TEMPKERNDIR}/initr* "${TEMPCOREDIR}/isolinux/gentoo.igz"
	gtest $? 'Failed to copy kernel and initrd'

elif [[ -n "${KERNEXT}" ]]; then
	gwarn "${KERNEXT} does not exist, ignoring..."
fi

if [[ -f "${MODEXT}" ]]; then
	gbegin "Replacing modules using ${MODEXT}"
	rm -rf "${TEMPOVERDIR}/lib/modules" &&
		tar jx -C "${TEMPOVERDIR}" -f "${MODEXT}"
	gtest $? 'Failed to replace modules'
elif [[ -n "${MODEXT}" ]]; then
	gwarn "${MODEXT} does not exist, ignoring..."
fi

gbegin 'Creating new squashfs filesystem'
mksquashfs "${TEMPOVERDIR}" "${TEMPCOREDIR}/image.squashfs" -noappend \
	> /dev/null 2>/dev/null
gtest $? 'Failed to create squashfs'

gbegin "Creating ${OUTPUT} core file"
tar cf "${OUTPUT}" -C "${TEMPCOREDIR}" .
gtest $? 'Failed to create new core tarball'

# Successful finish
cleanup
echo 'Remaster successful !'
exit 0

